﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Security.Cryptography;
using System.IO;

namespace BBMS.DLL.Base
{
    public class DPAPI
    {
        public static string Encrypt(string data, string password)
        {
            if (String.IsNullOrEmpty(data))
                throw new ArgumentException("No data given");
            if (String.IsNullOrEmpty(password))
                throw new ArgumentException("No password given");

            // setup the encryption algorithm
            Rfc2898DeriveBytes keyGenerator = new Rfc2898DeriveBytes(password, 8);
            Rijndael aes = Rijndael.Create();
            aes.IV = keyGenerator.GetBytes(aes.BlockSize / 8);
            aes.Key = keyGenerator.GetBytes(aes.KeySize / 8);

            // encrypt the data
            byte[] rawData = Encoding.Unicode.GetBytes(data);
            using (MemoryStream memoryStream = new MemoryStream())
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
            {
                memoryStream.Write(keyGenerator.Salt, 0, keyGenerator.Salt.Length);
                cryptoStream.Write(rawData, 0, rawData.Length);
                cryptoStream.Close();

                byte[] encrypted = memoryStream.ToArray();
                return Encoding.Unicode.GetString(encrypted);
            }
        }

        public static string Decrypt(string data, string password)
        {
            if (String.IsNullOrEmpty(data))
                throw new ArgumentException("No data given");
            if (String.IsNullOrEmpty(password))
                throw new ArgumentException("No password given");

            byte[] rawData = Encoding.Unicode.GetBytes(data);
            if (rawData.Length < 8)
                throw new ArgumentException("Invalid input data");

            // setup the decryption algorithm
            byte[] salt = new byte[8];
            for (int i = 0; i < salt.Length; i++)
                salt[i] = rawData[i];

            Rfc2898DeriveBytes keyGenerator = new Rfc2898DeriveBytes(password, salt);
            Rijndael aes = Rijndael.Create();
            aes.IV = keyGenerator.GetBytes(aes.BlockSize / 8);
            aes.Key = keyGenerator.GetBytes(aes.KeySize / 8);

            // decrypt the data
            using (MemoryStream memoryStream = new MemoryStream())
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cryptoStream.Write(rawData, 8, rawData.Length - 8);
                cryptoStream.Close();

                byte[] decrypted = memoryStream.ToArray();
                return Encoding.Unicode.GetString(decrypted);
            }
        }
    }
}
